﻿//=====================================================================================================
// LocalizationLibrary
// The Localization Library is a collection of reusable software components that provide 
// support for localization. This library enables you to localize WPF, Silverlight and WP7 applications.
// (http://localizationlibrary.codeplex.com)
//=====================================================================================================
// Author: Nicola Gallo (Website: www.nicola.gallo.name, Email: nicolagmt@hotmail.it) 
//=====================================================================================================

namespace ReflectionStudio.LocalizationLibrary
{
    //.NET References
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    //LocalizationLibrary References
    using LocalizationLibrary.Messaging;
    using ReflectionStudio.Core.Reflection;
    using LocalizationLibrary.Threading;

    /// <summary>
    /// Implements the task management.
    /// </summary>
    public partial class LocalizationManager
    {
        //Fields

        private static readonly LocalizationWorker LocalizationWorker = new LocalizationWorker();

        //Methods

        /// <summary>
        /// Initializes the task manager.
        /// </summary>
        private static void InitializeTaskManager()
        {
            LocalizationManager.LocalizationWorker.OnLocalization += (localizedToken) =>
            {
                if (localizedToken != null)
                {
                    lock (LocalizationManager.DynamicResourcesTable)
                    {
                        LocalizationManager.DynamicResourcesTable.Update(localizedToken, false);
                    }
                    String langCode;
                    lock (LocalizationManager.LocalizationWorker.TokensQueue)
                    {
                        langCode = LocalizationWorker.TokensQueue.CurrentLanguage.Code;
                    }
                    if (localizedToken.Language.Code.Equals(langCode))
                    {
                        LocalizationManager.PublishAllPropertiesValue(localizedToken.ResourceID);
                    }
                }
            };
            LocalizationManager.LocalizationWorker.Start();
            MessagingManager.OnMessage -= new MessageEventHandler(MessagingManager_OnMessage);
            MessagingManager.OnMessage += new MessageEventHandler(MessagingManager_OnMessage);
        }

        /// <summary>
        /// Called when the <see cref="MessagingManager"/> pusblishes a message.
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="e">Event arguments</param>
        private static void MessagingManager_OnMessage(object sender, MessageEventArgs e)
        {
            if (e.Message is LanguageMessage)
            {
                LanguageMessage message = e.Message as LanguageMessage;
                lock (LocalizationManager.LocalizationWorker.TokensQueue)
                {
                    LocalizationManager.LocalizationWorker.TokensQueue.CurrentLanguage = message.Language;
                }
                LocalizationManager.PublishAllPropertiesValue();
                DynamicResource[] unlocalizedResource = null;
                lock (LocalizationManager.DynamicResourcesTable)
                {
                    unlocalizedResource = LocalizationManager.DynamicResourcesTable.GetAllUnlocalizedResource(LocalizationManager.CurrentLanguage);
                }
                if (unlocalizedResource.Length > 0)
                {
                    foreach (var item in unlocalizedResource)
                    {
                        MessagingManager.Publish(new ResourceMessage(item, Operation.Processed));
                    }
                }
            }
            else if (e.Message is ResourceMessage)
            {
                ResourceMessage resourceMessage = e.Message as ResourceMessage;
                DynamicResource message = resourceMessage.Resource as DynamicResource;
                if (message != null)
                {
                    DynamicResourceToken token = message.GetToken(resourceMessage.Language ?? LocalizationManager.CurrentLanguage);
                    if (token != null)
                    {
                        if (token.Value == null)
                        {
                            lock (LocalizationManager.LocalizationWorker.TokensQueue)
                            {
                                LocalizationManager.LocalizationWorker.TokensQueue.Enqueue(token);
                            }
                        }
                        else
                        {
                            token.IsValide = false;
                            lock (LocalizationManager.LocalizationWorker)
                            {
                                LocalizationManager.LocalizationWorker.Abort(token);
                            }
                            lock (LocalizationManager.LocalizationWorker.TokensQueue)
                            {
                                LocalizationManager.LocalizationWorker.TokensQueue.Remove(token);
                            }
                            LocalizationManager.PublishAllPropertiesValue();
                        }
                    }
                }
            }
            else if (e.Message is LocalizationModelMessage)
            {
                LocalizationModelMessage message = e.Message as LocalizationModelMessage;
                LocalizationManager.PublishAllPropertiesValue(message.Instance);
            }
        }

        /// <summary>
        /// Sets the current <see cref="DynamicResourceToken"/> that are in localization.
        /// </summary>
        /// <param name="dynamicResourceTokens">Represents the array of <see cref="DynamicResourceToken"/>.</param>
        internal static void SetCurrentTokenLocalization(DynamicResourceToken[] dynamicResourceTokens)
        {
            bool isLocalizing = false;
            if ((dynamicResourceTokens != null) && (dynamicResourceTokens.Length > 0))
            {
                var queryCurrentToken = (from resourceToken in dynamicResourceTokens
                                         where resourceToken.Language == LocalizationManager.CurrentLanguage
                                         select resourceToken).ToArray();
                isLocalizing = (queryCurrentToken != null) && (queryCurrentToken.Length > 0);
                // TODO: [DEADLINE]deadline [OWNER]nicolagmt [EVENT]event [TASK]To optimize this method. Only the tokens needed  by user interface. 
            }
            LocalizationManager.EngineInfo.SetIsLocalizing(isLocalizing);
        }

        /// <summary>
        /// Publises all the properties value.
        /// </summary>
        private static void PublishAllPropertiesValue()
        {
            lock (LocalizationManager.LocalizationModelsTable)
            {
                LocalizationManager.LocalizationModelsTable.PublishAllPropertiesValue();
            }
        }

        /// <summary>
        /// Publishes the properties value of all the properties belonging at the input <paramref name="localiationModel"/>.
        /// </summary>
        /// <param name="localizationModel"></param>
        private static void PublishAllPropertiesValue(Object localizationModel)
        {
            List<Object> localizationModels = new List<object>();
            localizationModels.Add(localizationModel);
            lock (LocalizationManager.LocalizationModelsTable)
            {
                LocalizationManager.LocalizationModelsTable.PublishAllPropertiesValue(localizationModels);
            }
        }

        /// <summary>
        /// Publishes the value of all the properties bound at the input <paramref name="resourceID"/>.
        /// </summary>
        /// <param name="resourceID"></param>
        private static void PublishAllPropertiesValue(String resourceID)
        {
            // TODO: [DEADLINE]deadline [OWNER]nicolagmt [EVENT]event [TASK]This is only a temporary code. To Implement optimized code.
            LocalizationManager.PublishAllPropertiesValue();
        }
    }
}